import type { PageContainerRefs, PageState } from './types'
import { TextLayerBuilder } from 'pdfjs-dist/web/pdf_viewer'
import * as pdfjsLib from 'pdfjs-dist'

// 兼容 TextLayerBuilder 对 globalThis.pdfjsLib 的依赖
// 避免在 ESM 环境下未挂载导致的 AbortException 解构错误
if (!(globalThis as any).pdfjsLib) {
  ;(globalThis as any).pdfjsLib = pdfjsLib
}

export class PDFPage {
  private refs: PageContainerRefs
  private state: PageState
  private renderTask: any | null = null
  private textLayerBuilder: any | null = null
  private dpr = Math.max(1, Math.floor(window.devicePixelRatio || 1))

  constructor(index: number, wrapper: HTMLElement) {
    this.refs = { wrapper, canvas: null, textLayer: null }
    this.state = { index, rendered: false }
  }

  /**
   * @description 初始化页面容器
   * @param scale 缩放比例
   * @returns void
   */
  init(scale: number): void {
    this.state.metrics = { width: 0, height: 0, scale }
    this.refs.wrapper.style.position = 'relative'
    this.refs.wrapper.style.width = '100%'
    this.refs.wrapper.style.margin = '0 auto'
    this.refs.wrapper.style.display = 'block'
  }

  /**
   * @description 渲染页面到 Canvas
   * @param pageProxy PDF.js 的 PageProxy
   * @param scale 缩放比例
   * @returns Promise<void>
   */
  async render(pageProxy: any, scale: number): Promise<void> {
    if (this.renderTask) {
      try {
        this.renderTask.cancel()
      } catch {
        /* noop */
      }
      this.renderTask = null
    }

    const viewport = pageProxy.getViewport({ scale })
    const width = Math.floor(viewport.width)
    const height = Math.floor(viewport.height)

    let canvas = this.refs.canvas
    if (!canvas) {
      canvas = document.createElement('canvas')
      canvas.style.width = `${width}px`
      canvas.style.height = `${height}px`
      canvas.style.display = 'block'
      canvas.style.backgroundColor = '#fff'
      // 清空容器，但保留 textLayer（如果存在）
      const existingTextLayer = this.refs.textLayer
      this.refs.wrapper.innerHTML = ''
      this.refs.wrapper.appendChild(canvas)
      if (existingTextLayer) {
        this.refs.wrapper.appendChild(existingTextLayer)
      }
      this.refs.canvas = canvas
    } else {
      canvas.style.width = `${width}px`
      canvas.style.height = `${height}px`
    }

    const ctx = canvas.getContext('2d')
    if (!ctx) return

    canvas.width = width * this.dpr
    canvas.height = height * this.dpr
    ctx.setTransform(this.dpr, 0, 0, this.dpr, 0, 0)

    this.state.metrics = { width, height, scale }

    this.renderTask = pageProxy.render({ canvasContext: ctx, viewport })
    try {
      await this.renderTask.promise
      this.state.rendered = true
    } catch (e: any) {
      if (e && e.name === 'RenderingCancelledException') {
        this.state.rendered = false
        return
      }
      throw e
    }

    await this.renderTextLayer(pageProxy, viewport)
  }

  /**
   * @description 更新缩放并重绘
   * @param pageProxy PDF.js 的 PageProxy
   * @param scale 缩放比例
   * @returns Promise<void>
   */
  async updateScale(pageProxy: any, scale: number): Promise<void> {
    await this.render(pageProxy, scale)
  }

  /**
   * @description 释放页面资源
   * @returns void
   */
  destroy(): void {
    if (this.renderTask) {
      try {
        this.renderTask.cancel()
      } catch {
        /* noop */
      }
      this.renderTask = null
    }
    if (this.refs.canvas) {
      try {
        this.refs.wrapper.removeChild(this.refs.canvas)
      } catch {
        /* noop */
      }
      this.refs.canvas = null
    }
    if (this.refs.textLayer) {
      try {
        this.refs.wrapper.removeChild(this.refs.textLayer)
      } catch {
        /* noop */
      }
      this.refs.textLayer = null
      this.textLayerBuilder = null
    }
    this.state.rendered = false
  }

  /**
   * @description 获取页面状态
   * @returns 页面状态
   */
  getState(): PageState {
    return this.state
  }

  /**
   * @description 渲染文本层以支持选中与复制
   * @param pageProxy PDF.js 的 PageProxy
   * @param viewport 当前视口
   * @returns Promise<void>
   */
  private async renderTextLayer(pageProxy: any, viewport: any): Promise<void> {
    try {
      // 如果已存在 textLayerBuilder，先清理
      if (this.textLayerBuilder) {
        try {
          this.textLayerBuilder.cancel()
          if (
            this.textLayerBuilder.div &&
            this.textLayerBuilder.div.parentNode
          ) {
            this.textLayerBuilder.div.parentNode.removeChild(
              this.textLayerBuilder.div
            )
          }
        } catch {
          /* noop */
        }
        this.textLayerBuilder = null
      }

      // 移除旧的 textLayer（如果存在且不是 TextLayerBuilder 创建的）
      if (
        this.refs.textLayer &&
        this.refs.textLayer.parentNode &&
        this.refs.textLayer !== this.textLayerBuilder?.div
      ) {
        this.refs.wrapper.removeChild(this.refs.textLayer)
        this.refs.textLayer = null
      }

      // 创建新的 TextLayerBuilder
      this.textLayerBuilder = new TextLayerBuilder({
        pdfPage: pageProxy,
      })
      console.log('this.textLayerBuilder', this.textLayerBuilder)

      // 使用 viewport 的实际尺寸
      const viewportWidth = Math.floor(viewport.width)
      const viewportHeight = Math.floor(viewport.height)
      console.log('viewportWidth', viewportWidth)
      console.log('viewportHeight', viewportHeight)
      // 渲染文本层，使用与 Canvas 相同的 viewport
      await this.textLayerBuilder.render({
        viewport,
        textContentParams: {
          includeMarkedContent: true,
        },
      })

      // render 之后，TextLayerBuilder 的 div 应该已经创建并填充了内容
      if (this.textLayerBuilder.div) {
        const textLayerDiv = this.textLayerBuilder.div

        // 确保 div 不在错误的父节点中
        if (
          textLayerDiv.parentNode &&
          textLayerDiv.parentNode !== this.refs.wrapper
        ) {
          textLayerDiv.parentNode.removeChild(textLayerDiv)
        }

        // 设置样式，确保与 Canvas 完全对齐
        textLayerDiv.className = 'textLayer'
        textLayerDiv.style.position = 'absolute'
        textLayerDiv.style.left = '0'
        textLayerDiv.style.top = '0'
        textLayerDiv.style.width = `${Math.min(viewportWidth, viewportHeight)}px`
        textLayerDiv.style.height = `${Math.max(viewportWidth, viewportHeight)}px`
        textLayerDiv.style.transformOrigin = '0 0'
        textLayerDiv.style.pointerEvents = 'auto'
        textLayerDiv.style.userSelect = 'text'
        textLayerDiv.style.color = 'transparent'
        textLayerDiv.style.opacity = '1'
        textLayerDiv.style.lineHeight = '1'

        // 如果还没有添加到容器，则添加
        if (!textLayerDiv.parentNode) {
          this.refs.wrapper.appendChild(textLayerDiv)
        }

        this.refs.textLayer = textLayerDiv
      }
    } catch (e) {
      // 记录错误以便调试，但不影响主渲染
      console.warn('TextLayer render error:', e)
    }
  }
}
